﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Demo.Delegates
{
    class Program
    {
        delegate bool MyDelegate(int n);
        
        static IEnumerable<int> collection = new int[] {1,6,14,5,60,9,8};
        static void Main(string[] args)
        {
            // use 1 - use delegate to invoke a method with same signature
            MyDelegate del = new MyDelegate(FindLessThan5);
            Console.WriteLine(del(10));

            // use 2 - pass the method to another function accepting delegate with same signature
            FindItems(collection, FindLessThan5);
            FindItems(collection, FindGreaterThan10);

            // use 3 - anonymous method - pass code / method instead of delegate
            MyDelegate anonDel = delegate(int x) { return x < 2; };
            FindItems(collection, anonDel);
            // OR
            FindItems(collection, delegate(int x) {return x > 2;});

            // use 4 - Lambda expression - use lambda expression to replace delegate
            FindItems(collection, x => { return x > 15; });

            // use 5 - use lambda expression to instantiate delegate
            MyDelegate d1 = x => {return x > 8;};
            Console.WriteLine(d1(4));

            // Function Delegate - inbuilt generic delegate that takes generic types and returns a generic type
            Func<int, string, string> funcDelegate = (i, s) =>
            {
                Console.WriteLine("Integer : {0}. String :{1}", i, s);
                return s;
            };

            Action<int, string> actionDelegate = (i, s) =>
                {
                    Console.WriteLine("Integer : {0}. String :{1}", i, s);
                };

            Predicate<int> predicateDelegate = (i) =>
                {
                    return i == 0;
                };
            funcDelegate(5, "dummy");
            actionDelegate(6, "dummy");
            predicateDelegate(7);

            Console.Read();

        }

        static void FindItems(IEnumerable<int> collection, MyDelegate del)
        {
            foreach (var item in collection)
            {
                if (del(item))
                    Console.WriteLine(item);
            }
        }

        static bool FindLessThan5(int number)
        {
            return number < 5;
        }

        static bool FindGreaterThan10(int number)
        {
            return number > 10;
        }
    }
}
